import random
import re
from typing import List, Dict
from rmasm.word_syntax import Code

random_name_source = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'


def random_name(length: int = 16) -> str:
    """ 生成一个随机的名字
    """
    result = 'RN_'
    while len(result) < length:
        i = random.randrange(0, len(random_name_source))
        result += random_name_source[i]
    return result


_split_code_set_re = re.compile(r"((?:[^'\|]|'[^']*')+)")


def split_code_set(code: str) -> List[str]:
    """
    用某个分隔符切分代码块，自动将其中的单引号转换成双引号
    :param code: 一行代码集合
    """
    codes = [i.strip().replace('\'', '"') for i in _split_code_set_re.findall(code)]
    return codes


def code_replace(code: str, kv_map: dict, key_start: str = '<', key_end: str = '>') -> str:
    """ 替换代码中的宏参数，默认使用 < > 作为分隔符。
    """
    kv_map = kv_map.copy()
    c = re.compile(fr'{key_start}(\w+?|\w+ *= *\w+|\w+ +as +\w+|: *[\w, ]+){key_end}')
    split = c.split(code)
    result = ''

    for k, word in enumerate(split):
        if k % 2 == 1:
            if ' as ' in word:
                l, r = [i.strip() for i in word.split(' as ')]
                kv_map[r] = kv_map[l]
            elif '=' in word:
                l, r = [i.strip() for i in word.split('=')]
                kv_map[l] = r
            elif word.startswith(': '):
                args = [i.strip() for i in word[1:].split(',')]
                for k, a in enumerate(args):
                    kv_map[a] = kv_map[f'arg{k}']
            elif word not in kv_map:
                raise Exception(f"替换内容缺少参数：{word}")
            else:
                result += str(kv_map[word])
        else:
            result += word
    return result


if __name__ == '__main__':
    r = code_replace(
        '''
            a = <arg0>
            <arg1 as num>
            b = <num>
            <c233 = 233>
            c = <c233>        
        ''',
        kv_map={
            'arg0': 100,
            'arg1': 200
        }
    )
    print(r)


def load_code_file(path: str) -> 'Code':
    """ 读取一个代码文件，返回 Code 对象
    """
    try:
        f = open(path, 'r', encoding='utf-8')
        content = f.read()
        f.close()
    except Exception as e:
        raise Exception(f"打开代码文件 {path} 失败，可能是文件不存在或编码不是 utf-8.")
    return Code(content=content)
